home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / BYacc-CW 1.9 / reader.c < prev    next >
C/C++ Source or Header  |  1995-05-20  |  31KB  |  1,756 lines

  1. #include "defs.h"
  2.  
  3. #include <string.h>
  4.  
  5. /*  The line size must be a positive integer.  One hundred was chosen    */
  6. /*  because few lines in Yacc input grammars exceed 100 characters.    */
  7. /*  Note that if a line exceeds LINESIZE characters, the line buffer    */
  8. /*  will be expanded to accomodate it.                    */
  9.  
  10. #define LINESIZE 100
  11.  
  12. char *cache;
  13. int cinc, cache_size;
  14.  
  15. int ntags, tagmax;
  16. char **tag_table;
  17.  
  18. char saw_eof, unionized;
  19. char *cptr, *line;
  20. int linesize;
  21.  
  22. bucket *goal;
  23. int prec;
  24. int gensym;
  25. char last_was_action;
  26.  
  27. int maxitems;
  28. bucket **pitem;
  29.  
  30. int maxrules;
  31. bucket **plhs;
  32.  
  33. int name_pool_size;
  34. char *name_pool;
  35.  
  36. char line_format[] = "#line %d \"%s\"\n";
  37.  
  38.  
  39. static void cachec(int c)
  40. {
  41.     assert(cinc >= 0);
  42.     if (cinc >= cache_size)
  43.     {
  44.     cache_size += 256;
  45.     cache = REALLOC(cache, cache_size);
  46.     if (cache == 0) no_space();
  47.     }
  48.     cache[cinc] = c;
  49.     ++cinc;
  50. }
  51.  
  52.  
  53. static void get_line(void)
  54. {
  55.     register FILE *f = input_file;
  56.     register int c;
  57.     register int i;
  58.  
  59.     if (saw_eof || (c = getc(f)) == EOF)
  60.     {
  61.     if (line) { FREE(line); line = 0; }
  62.     cptr = 0;
  63.     saw_eof = 1;
  64.     return;
  65.     }
  66.  
  67.     if (line == 0 || linesize != (LINESIZE + 1))
  68.     {
  69.     if (line) FREE(line);
  70.     linesize = LINESIZE + 1;
  71.     line = MALLOC(linesize);
  72.     if (line == 0) no_space();
  73.     }
  74.  
  75.     i = 0;
  76.     ++lineno;
  77.     for (;;)
  78.     {
  79.     line[i]  =  c;
  80.     if (c == '\n') { cptr = line; return; }
  81.     if (++i >= linesize)
  82.     {
  83.         linesize += LINESIZE;
  84.         line = REALLOC(line, linesize);
  85.         if (line ==  0) no_space();
  86.     }
  87.     c = getc(f);
  88.     if (c ==  EOF)
  89.     {
  90.         line[i] = '\n';
  91.         saw_eof = 1;
  92.         cptr = line;
  93.         return;
  94.     }
  95.     }
  96. }
  97.  
  98.  
  99. static char *dup_line(void)
  100. {
  101.     register char *p, *s, *t;
  102.  
  103.     if (line == 0) return (0);
  104.     s = line;
  105.     while (*s != '\n') ++s;
  106.     p = MALLOC(s - line + 1);
  107.     if (p == 0) no_space();
  108.  
  109.     s = line;
  110.     t = p;
  111.     while ((*t++ = *s++) != '\n') continue;
  112.     return (p);
  113. }
  114.  
  115.  
  116. static void skip_comment(void)
  117. {
  118.     register char *s;
  119.  
  120.     int st_lineno = lineno;
  121.     char *st_line = dup_line();
  122.     char *st_cptr = st_line + (cptr - line);
  123.  
  124.     s = cptr + 2;
  125.     for (;;)
  126.     {
  127.     if (*s == '*' && s[1] == '/')
  128.     {
  129.         cptr = s + 2;
  130.         FREE(st_line);
  131.         return;
  132.     }
  133.     if (*s == '\n')
  134.     {
  135.         get_line();
  136.         if (line == 0)
  137.         unterminated_comment(st_lineno, st_line, st_cptr);
  138.         s = cptr;
  139.     }
  140.     else
  141.         ++s;
  142.     }
  143. }
  144.  
  145.  
  146. static int nextc(void)
  147. {
  148.     register char *s;
  149.  
  150.     if (line == 0)
  151.     {
  152.     get_line();
  153.     if (line == 0)
  154.         return (EOF);
  155.     }
  156.  
  157.     s = cptr;
  158.     for (;;)
  159.     {
  160.     switch (*s)
  161.     {
  162.     case '\n':
  163.         get_line();
  164.         if (line == 0) return (EOF);
  165.         s = cptr;
  166.         break;
  167.  
  168.     case ' ':
  169.     case '\t':
  170.     case '\f':
  171.     case '\r':
  172.     case '\v':
  173.     case ',':
  174.     case ';':
  175.         ++s;
  176.         break;
  177.  
  178.     case '\\':
  179.         cptr = s;
  180.         return ('%');
  181.  
  182.     case '/':
  183.         if (s[1] == '*')
  184.         {
  185.         cptr = s;
  186.         skip_comment();
  187.         s = cptr;
  188.         break;
  189.         }
  190.         else if (s[1] == '/')
  191.         {
  192.         get_line();
  193.         if (line == 0) return (EOF);
  194.         s = cptr;
  195.         break;
  196.         }
  197.         /* fall through */
  198.  
  199.     default:
  200.         cptr = s;
  201.         return (*s);
  202.     }
  203.     }
  204. }
  205.  
  206.  
  207. static int keyword(void)
  208. {
  209.     register int c;
  210.     char *t_cptr = cptr;
  211.  
  212.     c = *++cptr;
  213.     if (isalpha(c))
  214.     {
  215.     cinc = 0;
  216.     for (;;)
  217.     {
  218.         if (isalpha(c))
  219.         {
  220.         if (isupper(c)) c = tolower(c);
  221.         cachec(c);
  222.         }
  223.         else if (isdigit(c) || c == '_' || c == '.' || c == '$')
  224.         cachec(c);
  225.         else
  226.         break;
  227.         c = *++cptr;
  228.     }
  229.     cachec(NUL);
  230.  
  231.     if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0)
  232.         return (TOKEN);
  233.     if (strcmp(cache, "type") == 0)
  234.         return (TYPE);
  235.     if (strcmp(cache, "left") == 0)
  236.         return (LEFT);
  237.     if (strcmp(cache, "right") == 0)
  238.         return (RIGHT);
  239.     if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0)
  240.         return (NONASSOC);
  241.     if (strcmp(cache, "start") == 0)
  242.         return (START);
  243.     if (strcmp(cache, "union") == 0)
  244.         return (UNION);
  245.     if (strcmp(cache, "ident") == 0)
  246.         return (IDENT);
  247.     }
  248.     else
  249.     {
  250.     ++cptr;
  251.     if (c == '{')
  252.         return (TEXT);
  253.     if (c == '%' || c == '\\')
  254.         return (MARK);
  255.     if (c == '<')
  256.         return (LEFT);
  257.     if (c == '>')
  258.         return (RIGHT);
  259.     if (c == '0')
  260.         return (TOKEN);
  261.     if (c == '2')
  262.         return (NONASSOC);
  263.     }
  264.     syntax_error(lineno, line, t_cptr);
  265.     /*NOTREACHED*/ return(0);
  266. }
  267.  
  268.  
  269. static void copy_ident(void)
  270. {
  271.     register int c;
  272.     register FILE *f = output_file;
  273.  
  274.     c = nextc();
  275.     if (c == EOF) unexpected_EOF();
  276.     if (c != '"') syntax_error(lineno, line, cptr);
  277.     ++y_outline;
  278.     fprintf(f, "#ident \"");
  279.     for (;;)
  280.     {
  281.     c = *++cptr;
  282.     if (c == '\n')
  283.     {
  284.         fprintf(f, "\"\n");
  285.         return;
  286.     }
  287.     putc(c, f);
  288.     if (c == '"')
  289.     {
  290.         putc('\n', f);
  291.         ++cptr;
  292.         return;
  293.     }
  294.     }
  295. }
  296.  
  297.  
  298. static void copy_text(void)
  299. {
  300.     register int c;
  301.     int quote;
  302.     register FILE *f = text_file;
  303.     int need_newline = 0;
  304.     int t_lineno = lineno;
  305.     char *t_line = dup_line();
  306.     char *t_cptr = t_line + (cptr - line - 2);
  307.  
  308.     if (*cptr == '\n')
  309.     {
  310.     get_line();
  311.     if (line == 0)
  312.         unterminated_text(t_lineno, t_line, t_cptr);
  313.     }
  314.     if (!lflag) fprintf(f, line_format, lineno, input_file_name);
  315.  
  316. loop:
  317.     c = *cptr++;
  318.     switch (c)
  319.     {
  320.     case '\n':
  321.     next_line:
  322.     putc('\n', f);
  323.     need_newline = 0;
  324.     get_line();
  325.     if (line) goto loop;
  326.     unterminated_text(t_lineno, t_line, t_cptr);
  327.  
  328.     case '\'':
  329.     case '"':
  330.     {
  331.         int s_lineno = lineno;
  332.         char *s_line = dup_line();
  333.         char *s_cptr = s_line + (cptr - line - 1);
  334.  
  335.         quote = c;
  336.         putc(c, f);
  337.         for (;;)
  338.         {
  339.         c = *cptr++;
  340.         putc(c, f);
  341.         if (c == quote)
  342.         {
  343.             need_newline = 1;
  344.             FREE(s_line);
  345.             goto loop;
  346.         }
  347.         if (c == '\n')
  348.             unterminated_string(s_lineno, s_line, s_cptr);
  349.         if (c == '\\')
  350.         {
  351.             c = *cptr++;
  352.             putc(c, f);
  353.             if (c == '\n')
  354.             {
  355.             get_line();
  356.             if (line == 0)
  357.                 unterminated_string(s_lineno, s_line, s_cptr);
  358.             }
  359.         }
  360.         }
  361.     }
  362.  
  363.     case '/':
  364.     putc(c, f);
  365.     need_newline = 1;
  366.     c = *cptr;
  367.     if (c == '/')
  368.     {
  369.         putc('*', f);
  370.         while ((c = *++cptr) != '\n')
  371.         {
  372.         if (c == '*' && cptr[1] == '/')
  373.             fprintf(f, "* ");
  374.         else
  375.             putc(c, f);
  376.         }
  377.         fprintf(f, "*/");
  378.         goto next_line;
  379.     }
  380.     if (c == '*')
  381.     {
  382.         int c_lineno = lineno;
  383.         char *c_line = dup_line();
  384.         char *c_cptr = c_line + (cptr - line - 1);
  385.  
  386.         putc('*', f);
  387.         ++cptr;
  388.         for (;;)
  389.         {
  390.         c = *cptr++;
  391.         putc(c, f);
  392.         if (c == '*' && *cptr == '/')
  393.         {
  394.             putc('/', f);
  395.             ++cptr;
  396.             FREE(c_line);
  397.             goto loop;
  398.         }
  399.         if (c == '\n')
  400.         {
  401.             get_line();
  402.             if (line == 0)
  403.             unterminated_comment(c_lineno, c_line, c_cptr);
  404.         }
  405.         }
  406.     }
  407.     need_newline = 1;
  408.     goto loop;
  409.  
  410.     case '%':
  411.     case '\\':
  412.     if (*cptr == '}')
  413.     {
  414.         if (need_newline) putc('\n', f);
  415.         ++cptr;
  416.         FREE(t_line);
  417.         return;
  418.     }
  419.     /* fall through */
  420.  
  421.     default:
  422.     putc(c, f);
  423.     need_newline = 1;
  424.     goto loop;
  425.     }
  426. }
  427.  
  428.  
  429. static void copy_union(void)
  430. {
  431.     register int c;
  432.     int quote;
  433.     int depth;
  434.     int u_lineno = lineno;
  435.     char *u_line = dup_line();
  436.     char *u_cptr = u_line + (cptr - line - 6);
  437.  
  438.     if (unionized) over_unionized(cptr - 6);
  439.     unionized = 1;
  440.  
  441.     if (!lflag)
  442.     fprintf(text_file, line_format, lineno, input_file_name);
  443.  
  444.     fprintf(text_file, "typedef union");
  445.     if (dflag) fprintf(union_file, "typedef union");
  446.  
  447.     depth = 0;
  448. loop:
  449.     c = *cptr++;
  450.     putc(c, text_file);
  451.     if (dflag) putc(c, union_file);
  452.     switch (c)
  453.     {
  454.     case '\n':
  455.     next_line:
  456.     get_line();
  457.     if (line == 0) unterminated_union(u_lineno, u_line, u_cptr);
  458.     goto loop;
  459.  
  460.     case '{':
  461.     ++depth;
  462.     goto loop;
  463.  
  464.     case '}':
  465.     if (--depth == 0)
  466.     {
  467.         fprintf(text_file, " YYSTYPE;\n");
  468.         FREE(u_line);
  469.         return;
  470.     }
  471.     goto loop;
  472.  
  473.     case '\'':
  474.     case '"':
  475.     {
  476.         int s_lineno = lineno;
  477.         char *s_line = dup_line();
  478.         char *s_cptr = s_line + (cptr - line - 1);
  479.  
  480.         quote = c;
  481.         for (;;)
  482.         {
  483.         c = *cptr++;
  484.         putc(c, text_file);
  485.         if (dflag) putc(c, union_file);
  486.         if (c == quote)
  487.         {
  488.             FREE(s_line);
  489.             goto loop;
  490.         }
  491.         if (c == '\n')
  492.             unterminated_string(s_lineno, s_line, s_cptr);
  493.         if (c == '\\')
  494.         {
  495.             c = *cptr++;
  496.             putc(c, text_file);
  497.             if (dflag) putc(c, union_file);
  498.             if (c == '\n')
  499.             {
  500.             get_line();
  501.             if (line == 0)
  502.                 unterminated_string(s_lineno, s_line, s_cptr);
  503.             }
  504.         }
  505.         }
  506.     }
  507.  
  508.     case '/':
  509.     c = *cptr;
  510.     if (c == '/')
  511.     {
  512.         putc('*', text_file);
  513.         if (dflag) putc('*', union_file);
  514.         while ((c = *++cptr) != '\n')
  515.         {
  516.         if (c == '*' && cptr[1] == '/')
  517.         {
  518.             fprintf(text_file, "* ");
  519.             if (dflag) fprintf(union_file, "* ");
  520.         }
  521.         else
  522.         {
  523.             putc(c, text_file);
  524.             if (dflag) putc(c, union_file);
  525.         }
  526.         }
  527.         fprintf(text_file, "*/\n");
  528.         if (dflag) fprintf(union_file, "*/\n");
  529.         goto next_line;
  530.     }
  531.     if (c == '*')
  532.     {
  533.         int c_lineno = lineno;
  534.         char *c_line = dup_line();
  535.         char *c_cptr = c_line + (cptr - line - 1);
  536.  
  537.         putc('*', text_file);
  538.         if (dflag) putc('*', union_file);
  539.         ++cptr;
  540.         for (;;)
  541.         {
  542.         c = *cptr++;
  543.         putc(c, text_file);
  544.         if (dflag) putc(c, union_file);
  545.         if (c == '*' && *cptr == '/')
  546.         {
  547.             putc('/', text_file);
  548.             if (dflag) putc('/', union_file);
  549.             ++cptr;
  550.             FREE(c_line);
  551.             goto loop;
  552.         }
  553.         if (c == '\n')
  554.         {
  555.             get_line();
  556.             if (line == 0)
  557.             unterminated_comment(c_lineno, c_line, c_cptr);
  558.         }
  559.         }
  560.     }
  561.     goto loop;
  562.  
  563.     default:
  564.     goto loop;
  565.     }
  566. }
  567.  
  568.  
  569. static int hexval(int c)
  570. {
  571.     if (c >= '0' && c <= '9')
  572.     return (c - '0');
  573.     if (c >= 'A' && c <= 'F')
  574.     return (c - 'A' + 10);
  575.     if (c >= 'a' && c <= 'f')
  576.     return (c - 'a' + 10);
  577.     return (-1);
  578. }
  579.  
  580.  
  581. static bucket *get_literal(void)
  582. {
  583.     register int c, quote;
  584.     register int i;
  585.     register int n;
  586.     register char *s;
  587.     register bucket *bp;
  588.     int s_lineno = lineno;
  589.     char *s_line = dup_line();
  590.     char *s_cptr = s_line + (cptr - line);
  591.  
  592.     quote = *cptr++;
  593.     cinc = 0;
  594.     for (;;)
  595.     {
  596.     c = *cptr++;
  597.     if (c == quote) break;
  598.     if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr);
  599.     if (c == '\\')
  600.     {
  601.         char *c_cptr = cptr - 1;
  602.  
  603.         c = *cptr++;
  604.         switch (c)
  605.         {
  606.         case '\n':
  607.         get_line();
  608.         if (line == 0) unterminated_string(s_lineno, s_line, s_cptr);
  609.         continue;
  610.  
  611.         case '0': case '1': case '2': case '3':
  612.         case '4': case '5': case '6': case '7':
  613.         n = c - '0';
  614.         c = *cptr;
  615.         if (IS_OCTAL(c))
  616.         {
  617.             n = (n << 3) + (c - '0');
  618.             c = *++cptr;
  619.             if (IS_OCTAL(c))
  620.             {
  621.             n = (n << 3) + (c - '0');
  622.             ++cptr;
  623.             }
  624.         }
  625.         if (n > MAXCHAR) illegal_character(c_cptr);
  626.         c = n;
  627.             break;
  628.  
  629.         case 'x':
  630.         c = *cptr++;
  631.         n = hexval(c);
  632.         if (n < 0 || n >= 16)
  633.             illegal_character(c_cptr);
  634.         for (;;)
  635.         {
  636.             c = *cptr;
  637.             i = hexval(c);
  638.             if (i < 0 || i >= 16) break;
  639.             ++cptr;
  640.             n = (n << 4) + i;
  641.             if (n > MAXCHAR) illegal_character(c_cptr);
  642.         }
  643.         c = n;
  644.         break;
  645.  
  646.         case 'a': c = 7; break;
  647.         case 'b': c = '\b'; break;
  648.         case 'f': c = '\f'; break;
  649.         case 'n': c = '\n'; break;
  650.         case 'r': c = '\r'; break;
  651.         case 't': c = '\t'; break;
  652.         case 'v': c = '\v'; break;
  653.         }
  654.     }
  655.     cachec(c);
  656.     }
  657.     FREE(s_line);
  658.  
  659.     n = cinc;
  660.     s = MALLOC(n);
  661.     if (s == 0) no_space();
  662.     
  663.     for (i = 0; i < n; ++i)
  664.     s[i] = cache[i];
  665.  
  666.     cinc = 0;
  667.     if (n == 1)
  668.     cachec('\'');
  669.     else
  670.     cachec('"');
  671.  
  672.     for (i = 0; i < n; ++i)
  673.     {
  674.     c = ((unsigned char *)s)[i];
  675.     if (c == '\\' || c == cache[0])
  676.     {
  677.         cachec('\\');
  678.         cachec(c);
  679.     }
  680.     else if (isprint(c))
  681.         cachec(c);
  682.     else
  683.     {
  684.         cachec('\\');
  685.         switch (c)
  686.         {
  687.         case 7: cachec('a'); break;
  688.         case '\b': cachec('b'); break;
  689.         case '\f': cachec('f'); break;
  690.         case '\n': cachec('n'); break;
  691.         case '\r': cachec('r'); break;
  692.         case '\t': cachec('t'); break;
  693.         case '\v': cachec('v'); break;
  694.         default:
  695.         cachec(((c >> 6) & 7) + '0');
  696.         cachec(((c >> 3) & 7) + '0');
  697.         cachec((c & 7) + '0');
  698.         break;
  699.         }
  700.     }
  701.     }
  702.  
  703.     if (n == 1)
  704.     cachec('\'');
  705.     else
  706.     cachec('"');
  707.  
  708.     cachec(NUL);
  709.     bp = lookup(cache);
  710.     bp->class = TERM;
  711.     if (n == 1 && bp->value == UNDEFINED)
  712.     bp->value = *(unsigned char *)s;
  713.     FREE(s);
  714.  
  715.     return (bp);
  716. }
  717.  
  718.  
  719. static int is_reserved(char *name)
  720. {
  721.     char *s;
  722.  
  723.     if (strcmp(name, ".") == 0 ||
  724.         strcmp(name, "$accept") == 0 ||
  725.         strcmp(name, "$end") == 0)
  726.     return (1);
  727.  
  728.     if (name[0] == '$' && name[1] == '$' && isdigit(name[2]))
  729.     {
  730.     s = name + 3;
  731.     while (isdigit(*s)) ++s;
  732.     if (*s == NUL) return (1);
  733.     }
  734.  
  735.     return (0);
  736. }
  737.  
  738.  
  739. static bucket *get_name(void)
  740. {
  741.     register int c;
  742.  
  743.     cinc = 0;
  744.     for (c = *cptr; IS_IDENT(c); c = *++cptr)
  745.     cachec(c);
  746.     cachec(NUL);
  747.  
  748.     if (is_reserved(cache)) used_reserved(cache);
  749.  
  750.     return (lookup(cache));
  751. }
  752.  
  753.  
  754. static int get_number(void)
  755. {
  756.     register int c;
  757.     register int n;
  758.  
  759.     n = 0;
  760.     for (c = *cptr; isdigit(c); c = *++cptr)
  761.     n = 10*n + (c - '0');
  762.  
  763.     return (n);
  764. }
  765.  
  766.  
  767. static char *get_tag(void)
  768. {
  769.     register int c;
  770.     register int i;
  771.     register char *s;
  772.     int t_lineno = lineno;
  773.     char *t_line = dup_line();
  774.     char *t_cptr = t_line + (cptr - line);
  775.  
  776.     ++cptr;
  777.     c = nextc();
  778.     if (c == EOF) unexpected_EOF();
  779.     if (!isalpha(c) && c != '_' && c != '$')
  780.     illegal_tag(t_lineno, t_line, t_cptr);
  781.  
  782.     cinc = 0;
  783.     do { cachec(c); c = *++cptr; } while (IS_IDENT(c));
  784.     cachec(NUL);
  785.  
  786.     c = nextc();
  787.     if (c == EOF) unexpected_EOF();
  788.     if (c != '>')
  789.     illegal_tag(t_lineno, t_line, t_cptr);
  790.     ++cptr;
  791.  
  792.     for (i = 0; i < ntags; ++i)
  793.     {
  794.     if (strcmp(cache, tag_table[i]) == 0)
  795.         return (tag_table[i]);
  796.     }
  797.  
  798.     if (ntags >= tagmax)
  799.     {
  800.     tagmax += 16;
  801.     tag_table = (char **)
  802.             (tag_table ? REALLOC(tag_table, tagmax*sizeof(char *))
  803.                    : MALLOC(tagmax*sizeof(char *)));
  804.     if (tag_table == 0) no_space();
  805.     }
  806.  
  807.     s = MALLOC(cinc);
  808.     if  (s == 0) no_space();
  809.     strcpy(s, cache);
  810.     tag_table[ntags] = s;
  811.     ++ntags;
  812.     FREE(t_line);
  813.     return (s);
  814. }
  815.  
  816.  
  817. static void declare_tokens(int assoc)
  818. {
  819.     register int c;
  820.     register bucket *bp;
  821.     int value;
  822.     char *tag = 0;
  823.  
  824.     if (assoc != TOKEN) ++prec;
  825.  
  826.     c = nextc();
  827.     if (c == EOF) unexpected_EOF();
  828.     if (c == '<')
  829.     {
  830.     tag = get_tag();
  831.     c = nextc();
  832.     if (c == EOF) unexpected_EOF();
  833.     }
  834.  
  835.     for (;;)
  836.     {
  837.     if (isalpha(c) || c == '_' || c == '.' || c == '$')
  838.         bp = get_name();
  839.     else if (c == '\'' || c == '"')
  840.         bp = get_literal();
  841.     else
  842.         return;
  843.  
  844.     if (bp == goal) tokenized_start(bp->name);
  845.     bp->class = TERM;
  846.  
  847.     if (tag)
  848.     {
  849.         if (bp->tag && tag != bp->tag)
  850.         retyped_warning(bp->name);
  851.         bp->tag = tag;
  852.     }
  853.  
  854.     if (assoc != TOKEN)
  855.     {
  856.         if (bp->prec && prec != bp->prec)
  857.         reprec_warning(bp->name);
  858.         bp->assoc = assoc;
  859.         bp->prec = prec;
  860.     }
  861.  
  862.     c = nextc();
  863.     if (c == EOF) unexpected_EOF();
  864.     value = UNDEFINED;
  865.     if (isdigit(c))
  866.     {
  867.         value = get_number();
  868.         if (bp->value != UNDEFINED && value != bp->value)
  869.         revalued_warning(bp->name);
  870.         bp->value = value;
  871.         c = nextc();
  872.         if (c == EOF) unexpected_EOF();
  873.     }
  874.     }
  875. }
  876.  
  877.  
  878. static void declare_types(void)
  879. {
  880.     register int c;
  881.     register bucket *bp;
  882.     char *tag;
  883.  
  884.     c = nextc();
  885.     if (c == EOF) unexpected_EOF();
  886.     if (c != '<') syntax_error(lineno, line, cptr);
  887.     tag = get_tag();
  888.  
  889.     for (;;)
  890.     {
  891.     c = nextc();
  892.     if (isalpha(c) || c == '_' || c == '.' || c == '$')
  893.         bp = get_name();
  894.     else if (c == '\'' || c == '"')
  895.         bp = get_literal();
  896.     else
  897.         return;
  898.  
  899.     if (bp->tag && tag != bp->tag)
  900.         retyped_warning(bp->name);
  901.     bp->tag = tag;
  902.     }
  903. }
  904.  
  905.  
  906. static void declare_start(void)
  907. {
  908.     register int c;
  909.     register bucket *bp;
  910.  
  911.     c = nextc();
  912.     if (c == EOF) unexpected_EOF();
  913.     if (!isalpha(c) && c != '_' && c != '.' && c != '$')
  914.     syntax_error(lineno, line, cptr);
  915.     bp = get_name();
  916.     if (bp->class == TERM)
  917.     terminal_start(bp->name);
  918.     if (goal && goal != bp)
  919.     restarted_warning();
  920.     goal = bp;
  921. }
  922.  
  923.  
  924. static void read_declarations(void)
  925. {
  926.     register int c, k;
  927.  
  928.     cache_size = 256;
  929.     cache = MALLOC(cache_size);
  930.     if (cache == 0) no_space();
  931.  
  932.     for (;;)
  933.     {
  934.     c = nextc();
  935.     if (c == EOF) unexpected_EOF();
  936.     if (c != '%') syntax_error(lineno, line, cptr);
  937.     switch (k = keyword())
  938.     {
  939.     case MARK:
  940.         return;
  941.  
  942.     case IDENT:
  943.         copy_ident();
  944.         break;
  945.  
  946.     case TEXT:
  947.         copy_text();
  948.         break;
  949.  
  950.     case UNION:
  951.         copy_union();
  952.         break;
  953.  
  954.     case TOKEN:
  955.     case LEFT:
  956.     case RIGHT:
  957.     case NONASSOC:
  958.         declare_tokens(k);
  959.         break;
  960.  
  961.     case TYPE:
  962.         declare_types();
  963.         break;
  964.  
  965.     case START:
  966.         declare_start();
  967.         break;
  968.     }
  969.     }
  970. }
  971.  
  972.  
  973. static void initialize_grammar(void)
  974. {
  975.     nitems = 4;
  976.     maxitems = 300;
  977.     pitem = (bucket **) MALLOC(maxitems*sizeof(bucket *));
  978.     if (pitem == 0) no_space();
  979.     pitem[0] = 0;
  980.     pitem[1] = 0;
  981.     pitem[2] = 0;
  982.     pitem[3] = 0;
  983.  
  984.     nrules = 3;
  985.     maxrules = 100;
  986.     plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *));
  987.     if (plhs == 0) no_space();
  988.     plhs[0] = 0;
  989.     plhs[1] = 0;
  990.     plhs[2] = 0;
  991.     rprec = (short *) MALLOC(maxrules*sizeof(short));
  992.     if (rprec == 0) no_space();
  993.     rprec[0] = 0;
  994.     rprec[1] = 0;
  995.     rprec[2] = 0;
  996.     rassoc = (char *) MALLOC(maxrules*sizeof(char));
  997.     if (rassoc == 0) no_space();
  998.     rassoc[0] = TOKEN;
  999.     rassoc[1] = TOKEN;
  1000.     rassoc[2] = TOKEN;
  1001. }
  1002.  
  1003.  
  1004. static void expand_items(void)
  1005. {
  1006.     maxitems += 300;
  1007.     pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *));
  1008.     if (pitem == 0) no_space();
  1009. }
  1010.  
  1011.  
  1012. static void expand_rules(void)
  1013. {
  1014.     maxrules += 100;
  1015.     plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *));
  1016.     if (plhs == 0) no_space();
  1017.     rprec = (short *) REALLOC(rprec, maxrules*sizeof(short));
  1018.     if (rprec == 0) no_space();
  1019.     rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char));
  1020.     if (rassoc == 0) no_space();
  1021. }
  1022.  
  1023. static void start_rule(register bucket *bp, int s_lineno)
  1024. {
  1025.     if (bp->class == TERM)
  1026.     terminal_lhs(s_lineno);
  1027.     bp->class = NONTERM;
  1028.     if (nrules >= maxrules)
  1029.     expand_rules();
  1030.     plhs[nrules] = bp;
  1031.     rprec[nrules] = UNDEFINED;
  1032.     rassoc[nrules] = TOKEN;
  1033. }
  1034.  
  1035. static void advance_to_start(void)
  1036. {
  1037.     register int c;
  1038.     register bucket *bp;
  1039.     char *s_cptr;
  1040.     int s_lineno;
  1041.  
  1042.     for (;;)
  1043.     {
  1044.     c = nextc();
  1045.     if (c != '%') break;
  1046.     s_cptr = cptr;
  1047.     switch (keyword())
  1048.     {
  1049.     case MARK:
  1050.         no_grammar();
  1051.  
  1052.     case TEXT:
  1053.         copy_text();
  1054.         break;
  1055.  
  1056.     case START:
  1057.         declare_start();
  1058.         break;
  1059.  
  1060.     default:
  1061.         syntax_error(lineno, line, s_cptr);
  1062.     }
  1063.     }
  1064.  
  1065.     c = nextc();
  1066.     if (!isalpha(c) && c != '_' && c != '.' && c != '_')
  1067.     syntax_error(lineno, line, cptr);
  1068.     bp = get_name();
  1069.     if (goal == 0)
  1070.     {
  1071.     if (bp->class == TERM)
  1072.         terminal_start(bp->name);
  1073.     goal = bp;
  1074.     }
  1075.  
  1076.     s_lineno = lineno;
  1077.     c = nextc();
  1078.     if (c == EOF) unexpected_EOF();
  1079.     if (c != ':') syntax_error(lineno, line, cptr);
  1080.     start_rule(bp, s_lineno);
  1081.     ++cptr;
  1082. }
  1083.  
  1084.  
  1085.  
  1086. static void end_rule(void)
  1087. {
  1088.     register int i;
  1089.  
  1090.     if (!last_was_action && plhs[nrules]->tag)
  1091.     {
  1092.     for (i = nitems - 1; pitem[i]; --i) continue;
  1093.     if (pitem[i+1] == 0 || pitem[i+1]->tag != plhs[nrules]->tag)
  1094.         default_action_warning();
  1095.     }
  1096.  
  1097.     last_was_action = 0;
  1098.     if (nitems >= maxitems) expand_items();
  1099.     pitem[nitems] = 0;
  1100.     ++nitems;
  1101.     ++nrules;
  1102. }
  1103.  
  1104.  
  1105. static void insert_empty_rule(void)
  1106. {
  1107.     register bucket *bp, **bpp;
  1108.  
  1109.     assert(cache);
  1110.     sprintf(cache, "$$%d", ++gensym);
  1111.     bp = make_bucket(cache);
  1112.     last_symbol->next = bp;
  1113.     last_symbol = bp;
  1114.     bp->tag = plhs[nrules]->tag;
  1115.     bp->class = NONTERM;
  1116.  
  1117.     if ((nitems += 2) > maxitems)
  1118.     expand_items();
  1119.     bpp = pitem + nitems - 1;
  1120.     *bpp-- = bp;
  1121.     while ((bpp[0] = bpp[-1])!=0) --bpp;
  1122.  
  1123.     if (++nrules >= maxrules)
  1124.     expand_rules();
  1125.     plhs[nrules] = plhs[nrules-1];
  1126.     plhs[nrules-1] = bp;
  1127.     rprec[nrules] = rprec[nrules-1];
  1128.     rprec[nrules-1] = 0;
  1129.     rassoc[nrules] = rassoc[nrules-1];
  1130.     rassoc[nrules-1] = TOKEN;
  1131. }
  1132.  
  1133.  
  1134. static void add_symbol(void)
  1135. {
  1136.     register int c;
  1137.     register bucket *bp;
  1138.     int s_lineno = lineno;
  1139.  
  1140.     c = *cptr;
  1141.     if (c == '\'' || c == '"')
  1142.     bp = get_literal();
  1143.     else
  1144.     bp = get_name();
  1145.  
  1146.     c = nextc();
  1147.     if (c == ':')
  1148.     {
  1149.     end_rule();
  1150.     start_rule(bp, s_lineno);
  1151.     ++cptr;
  1152.     return;
  1153.     }
  1154.  
  1155.     if (last_was_action)
  1156.     insert_empty_rule();
  1157.     last_was_action = 0;
  1158.  
  1159.     if (++nitems > maxitems)
  1160.     expand_items();
  1161.     pitem[nitems-1] = bp;
  1162. }
  1163.  
  1164.  
  1165. static void copy_action(void)
  1166. {
  1167.     register int c;
  1168.     register int i, n;
  1169.     int depth;
  1170.     int quote;
  1171.     char *tag;
  1172.     register FILE *f = action_file;
  1173.     int a_lineno = lineno;
  1174.     char *a_line = dup_line();
  1175.     char *a_cptr = a_line + (cptr - line);
  1176.  
  1177.     if (last_was_action)
  1178.     insert_empty_rule();
  1179.     last_was_action = 1;
  1180.  
  1181.     fprintf(f, "case %d:\n", nrules - 2);
  1182.     if (!lflag)
  1183.     fprintf(f, line_format, lineno, input_file_name);
  1184.     if (*cptr == '=') ++cptr;
  1185.  
  1186.     n = 0;
  1187.     for (i = nitems - 1; pitem[i]; --i) ++n;
  1188.  
  1189.     depth = 0;
  1190. loop:
  1191.     c = *cptr;
  1192.     if (c == '$')
  1193.     {
  1194.     if (cptr[1] == '<')
  1195.     {
  1196.         int d_lineno = lineno;
  1197.         char *d_line = dup_line();
  1198.         char *d_cptr = d_line + (cptr - line);
  1199.  
  1200.         ++cptr;
  1201.         tag = get_tag();
  1202.         c = *cptr;
  1203.         if (c == '$')
  1204.         {
  1205.         fprintf(f, "yyval.%s", tag);
  1206.         ++cptr;
  1207.         FREE(d_line);
  1208.         goto loop;
  1209.         }
  1210.         else if (isdigit(c))
  1211.         {
  1212.         i = get_number();
  1213.         if (i > n) dollar_warning(d_lineno, i);
  1214.         fprintf(f, "yyvsp[%d].%s", i - n, tag);
  1215.         FREE(d_line);
  1216.         goto loop;
  1217.         }
  1218.         else if (c == '-' && isdigit(cptr[1]))
  1219.         {
  1220.         ++cptr;
  1221.         i = -get_number() - n;
  1222.         fprintf(f, "yyvsp[%d].%s", i, tag);
  1223.         FREE(d_line);
  1224.         goto loop;
  1225.         }
  1226.         else
  1227.         dollar_error(d_lineno, d_line, d_cptr);
  1228.     }
  1229.     else if (cptr[1] == '$')
  1230.     {
  1231.         if (ntags)
  1232.         {
  1233.         tag = plhs[nrules]->tag;
  1234.         if (tag == 0) untyped_lhs();
  1235.         fprintf(f, "yyval.%s", tag);
  1236.         }
  1237.         else
  1238.         fprintf(f, "yyval");
  1239.         cptr += 2;
  1240.         goto loop;
  1241.     }
  1242.     else if (isdigit(cptr[1]))
  1243.     {
  1244.         ++cptr;
  1245.         i = get_number();
  1246.         if (ntags)
  1247.         {
  1248.         if (i <= 0 || i > n)
  1249.             unknown_rhs(i);
  1250.         tag = pitem[nitems + i - n - 1]->tag;
  1251.         if (tag == 0) untyped_rhs(i, pitem[nitems + i - n - 1]->name);
  1252.         fprintf(f, "yyvsp[%d].%s", i - n, tag);
  1253.         }
  1254.         else
  1255.         {
  1256.         if (i > n)
  1257.             dollar_warning(lineno, i);
  1258.         fprintf(f, "yyvsp[%d]", i - n);
  1259.         }
  1260.         goto loop;
  1261.     }
  1262.     else if (cptr[1] == '-')
  1263.     {
  1264.         cptr += 2;
  1265.         i = get_number();
  1266.         if (ntags)
  1267.         unknown_rhs(-i);
  1268.         fprintf(f, "yyvsp[%d]", -i - n);
  1269.         goto loop;
  1270.     }
  1271.     }
  1272.     if (isalpha(c) || c == '_' || c == '$')
  1273.     {
  1274.     do
  1275.     {
  1276.         putc(c, f);
  1277.         c = *++cptr;
  1278.     } while (isalnum(c) || c == '_' || c == '$');
  1279.     goto loop;
  1280.     }
  1281.     putc(c, f);
  1282.     ++cptr;
  1283.     switch (c)
  1284.     {
  1285.     case '\n':
  1286.     next_line:
  1287.     get_line();
  1288.     if (line) goto loop;
  1289.     unterminated_action(a_lineno, a_line, a_cptr);
  1290.  
  1291.     case ';':
  1292.     if (depth > 0) goto loop;
  1293.     fprintf(f, "\nbreak;\n");
  1294.     return;
  1295.  
  1296.     case '{':
  1297.     ++depth;
  1298.     goto loop;
  1299.  
  1300.     case '}':
  1301.     if (--depth > 0) goto loop;
  1302.     fprintf(f, "\nbreak;\n");
  1303.     return;
  1304.  
  1305.     case '\'':
  1306.     case '"':
  1307.     {
  1308.         int s_lineno = lineno;
  1309.         char *s_line = dup_line();
  1310.         char *s_cptr = s_line + (cptr - line - 1);
  1311.  
  1312.         quote = c;
  1313.         for (;;)
  1314.         {
  1315.         c = *cptr++;
  1316.         putc(c, f);
  1317.         if (c == quote)
  1318.         {
  1319.             FREE(s_line);
  1320.             goto loop;
  1321.         }
  1322.         if (c == '\n')
  1323.             unterminated_string(s_lineno, s_line, s_cptr);
  1324.         if (c == '\\')
  1325.         {
  1326.             c = *cptr++;
  1327.             putc(c, f);
  1328.             if (c == '\n')
  1329.             {
  1330.             get_line();
  1331.             if (line == 0)
  1332.                 unterminated_string(s_lineno, s_line, s_cptr);
  1333.             }
  1334.         }
  1335.         }
  1336.     }
  1337.  
  1338.     case '/':
  1339.     c = *cptr;
  1340.     if (c == '/')
  1341.     {
  1342.         putc('*', f);
  1343.         while ((c = *++cptr) != '\n')
  1344.         {
  1345.         if (c == '*' && cptr[1] == '/')
  1346.             fprintf(f, "* ");
  1347.         else
  1348.             putc(c, f);
  1349.         }
  1350.         fprintf(f, "*/\n");
  1351.         goto next_line;
  1352.     }
  1353.     if (c == '*')
  1354.     {
  1355.         int c_lineno = lineno;
  1356.         char *c_line = dup_line();
  1357.         char *c_cptr = c_line + (cptr - line - 1);
  1358.  
  1359.         putc('*', f);
  1360.         ++cptr;
  1361.         for (;;)
  1362.         {
  1363.         c = *cptr++;
  1364.         putc(c, f);
  1365.         if (c == '*' && *cptr == '/')
  1366.         {
  1367.             putc('/', f);
  1368.             ++cptr;
  1369.             FREE(c_line);
  1370.             goto loop;
  1371.         }
  1372.         if (c == '\n')
  1373.         {
  1374.             get_line();
  1375.             if (line == 0)
  1376.             unterminated_comment(c_lineno, c_line, c_cptr);
  1377.         }
  1378.         }
  1379.     }
  1380.     goto loop;
  1381.  
  1382.     default:
  1383.     goto loop;
  1384.     }
  1385. }
  1386.  
  1387.  
  1388. static int mark_symbol(void)
  1389. {
  1390.     register int c;
  1391.     register bucket *bp;
  1392.  
  1393.     c = cptr[1];
  1394.     if (c == '%' || c == '\\')
  1395.     {
  1396.     cptr += 2;
  1397.     return (1);
  1398.     }
  1399.  
  1400.     if (c == '=')
  1401.     cptr += 2;
  1402.     else if ((c == 'p' || c == 'P') &&
  1403.          ((c = cptr[2]) == 'r' || c == 'R') &&
  1404.          ((c = cptr[3]) == 'e' || c == 'E') &&
  1405.          ((c = cptr[4]) == 'c' || c == 'C') &&
  1406.          ((c = cptr[5], !IS_IDENT(c))))
  1407.     cptr += 5;
  1408.     else
  1409.     syntax_error(lineno, line, cptr);
  1410.  
  1411.     c = nextc();
  1412.     if (isalpha(c) || c == '_' || c == '.' || c == '$')
  1413.     bp = get_name();
  1414.     else if (c == '\'' || c == '"')
  1415.     bp = get_literal();
  1416.     else
  1417.     {
  1418.     syntax_error(lineno, line, cptr);
  1419.     /*NOTREACHED*/
  1420.     }
  1421.  
  1422.     if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
  1423.     prec_redeclared();
  1424.  
  1425.     rprec[nrules] = bp->prec;
  1426.     rassoc[nrules] = bp->assoc;
  1427.     return (0);
  1428. }
  1429.  
  1430.  
  1431. static void read_grammar(void)
  1432. {
  1433.     register int c;
  1434.  
  1435.     initialize_grammar();
  1436.     advance_to_start();
  1437.  
  1438.     for (;;)
  1439.     {
  1440.     c = nextc();
  1441.     if (c == EOF) break;
  1442.     if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' ||
  1443.         c == '"')
  1444.         add_symbol();
  1445.     else if (c == '{' || c == '=')
  1446.         copy_action();
  1447.     else if (c == '|')
  1448.     {
  1449.         end_rule();
  1450.         start_rule(plhs[nrules-1], 0);
  1451.         ++cptr;
  1452.     }
  1453.     else if (c == '%')
  1454.     {
  1455.         if (mark_symbol()) break;
  1456.     }
  1457.     else
  1458.         syntax_error(lineno, line, cptr);
  1459.     }
  1460.     end_rule();
  1461. }
  1462.  
  1463.  
  1464. static void free_tags(void)
  1465. {
  1466.     register int i;
  1467.  
  1468.     if (tag_table == 0) return;
  1469.  
  1470.     for (i = 0; i < ntags; ++i)
  1471.     {
  1472.     assert(tag_table[i]);
  1473.     FREE(tag_table[i]);
  1474.     }
  1475.     FREE(tag_table);
  1476. }
  1477.  
  1478.  
  1479. static void pack_names(void)
  1480. {
  1481.     register bucket *bp;
  1482.     register char *p, *s, *t;
  1483.  
  1484.     name_pool_size = 13;  /* 13 == sizeof("$end") + sizeof("$accept") */
  1485.     for (bp = first_symbol; bp; bp = bp->next)
  1486.     name_pool_size += strlen(bp->name) + 1;
  1487.     name_pool = MALLOC(name_pool_size);
  1488.     if (name_pool == 0) no_space();
  1489.  
  1490.     strcpy(name_pool, "$accept");
  1491.     strcpy(name_pool+8, "$end");
  1492.     t = name_pool + 13;
  1493.     for (bp = first_symbol; bp; bp = bp->next)
  1494.     {
  1495.     p = t;
  1496.     s = bp->name;
  1497.     while ((*t++ = *s++)!=0) continue;
  1498.     FREE(bp->name);
  1499.     bp->name = p;
  1500.     }
  1501. }
  1502.  
  1503.  
  1504. static void check_symbols(void)
  1505. {
  1506.     register bucket *bp;
  1507.  
  1508.     if (goal->class == UNKNOWN)
  1509.     undefined_goal(goal->name);
  1510.  
  1511.     for (bp = first_symbol; bp; bp = bp->next)
  1512.     {
  1513.     if (bp->class == UNKNOWN)
  1514.     {
  1515.         undefined_symbol_warning(bp->name);
  1516.         bp->class = TERM;
  1517.     }
  1518.     }
  1519. }
  1520.  
  1521.  
  1522. static void pack_symbols(void)
  1523. {
  1524.     register bucket *bp;
  1525.     register bucket **v;
  1526.     register int i, j, k, n;
  1527.  
  1528.     nsyms = 2;
  1529.     ntokens = 1;
  1530.     for (bp = first_symbol; bp; bp = bp->next)
  1531.     {
  1532.     ++nsyms;
  1533.     if (bp->class == TERM) ++ntokens;
  1534.     }
  1535.     start_symbol = ntokens;
  1536.     nvars = nsyms - ntokens;
  1537.  
  1538.     symbol_name = (char **) MALLOC(nsyms*sizeof(char *));
  1539.     if (symbol_name == 0) no_space();
  1540.     symbol_value = (short *) MALLOC(nsyms*sizeof(short));
  1541.     if (symbol_value == 0) no_space();
  1542.     symbol_prec = (short *) MALLOC(nsyms*sizeof(short));
  1543.     if (symbol_prec == 0) no_space();
  1544.     symbol_assoc = MALLOC(nsyms);
  1545.     if (symbol_assoc == 0) no_space();
  1546.  
  1547.     v = (bucket **) MALLOC(nsyms*sizeof(bucket *));
  1548.     if (v == 0) no_space();
  1549.  
  1550.     v[0] = 0;
  1551.     v[start_symbol] = 0;
  1552.  
  1553.     i = 1;
  1554.     j = start_symbol + 1;
  1555.     for (bp = first_symbol; bp; bp = bp->next)
  1556.     {
  1557.     if (bp->class == TERM)
  1558.         v[i++] = bp;
  1559.     else
  1560.         v[j++] = bp;
  1561.     }
  1562.     assert(i == ntokens && j == nsyms);
  1563.  
  1564.     for (i = 1; i < ntokens; ++i)
  1565.     v[i]->index = i;
  1566.  
  1567.     goal->index = start_symbol + 1;
  1568.     k = start_symbol + 2;
  1569.     while (++i < nsyms)
  1570.     if (v[i] != goal)
  1571.     {
  1572.         v[i]->index = k;
  1573.         ++k;
  1574.     }
  1575.  
  1576.     goal->value = 0;
  1577.     k = 1;
  1578.     for (i = start_symbol + 1; i < nsyms; ++i)
  1579.     {
  1580.     if (v[i] != goal)
  1581.     {
  1582.         v[i]->value = k;
  1583.         ++k;
  1584.     }
  1585.     }
  1586.  
  1587.     k = 0;
  1588.     for (i = 1; i < ntokens; ++i)
  1589.     {
  1590.     n = v[i]->value;
  1591.     if (n > 256)
  1592.     {
  1593.         for (j = k++; j > 0 && symbol_value[j-1] > n; --j)
  1594.         symbol_value[j] = symbol_value[j-1];
  1595.         symbol_value[j] = n;
  1596.     }
  1597.     }
  1598.  
  1599.     if (v[1]->value == UNDEFINED)
  1600.     v[1]->value = 256;
  1601.  
  1602.     j = 0;
  1603.     n = 257;
  1604.     for (i = 2; i < ntokens; ++i)
  1605.     {
  1606.     if (v[i]->value == UNDEFINED)
  1607.     {
  1608.         while (j < k && n == symbol_value[j])
  1609.         {
  1610.         while (++j < k && n == symbol_value[j]) continue;
  1611.         ++n;
  1612.         }
  1613.         v[i]->value = n;
  1614.         ++n;
  1615.     }
  1616.     }
  1617.  
  1618.     symbol_name[0] = name_pool + 8;
  1619.     symbol_value[0] = 0;
  1620.     symbol_prec[0] = 0;
  1621.     symbol_assoc[0] = TOKEN;
  1622.     for (i = 1; i < ntokens; ++i)
  1623.     {
  1624.     symbol_name[i] = v[i]->name;
  1625.     symbol_value[i] = v[i]->value;
  1626.     symbol_prec[i] = v[i]->prec;
  1627.     symbol_assoc[i] = v[i]->assoc;
  1628.     }
  1629.     symbol_name[start_symbol] = name_pool;
  1630.     symbol_value[start_symbol] = -1;
  1631.     symbol_prec[start_symbol] = 0;
  1632.     symbol_assoc[start_symbol] = TOKEN;
  1633.     for (++i; i < nsyms; ++i)
  1634.     {
  1635.     k = v[i]->index;
  1636.     symbol_name[k] = v[i]->name;
  1637.     symbol_value[k] = v[i]->value;
  1638.     symbol_prec[k] = v[i]->prec;
  1639.     symbol_assoc[k] = v[i]->assoc;
  1640.     }
  1641.  
  1642.     FREE(v);
  1643. }
  1644.  
  1645.  
  1646. static void pack_grammar(void)
  1647. {
  1648.     register int i, j;
  1649.     int assoc, prec;
  1650.  
  1651.     ritem = (short *) MALLOC(nitems*sizeof(short));
  1652.     if (ritem == 0) no_space();
  1653.     rlhs = (short *) MALLOC(nrules*sizeof(short));
  1654.     if (rlhs == 0) no_space();
  1655.     rrhs = (short *) MALLOC((nrules+1)*sizeof(short));
  1656.     if (rrhs == 0) no_space();
  1657.     rprec = (short *) REALLOC(rprec, nrules*sizeof(short));
  1658.     if (rprec == 0) no_space();
  1659.     rassoc = REALLOC(rassoc, nrules);
  1660.     if (rassoc == 0) no_space();
  1661.  
  1662.     ritem[0] = -1;
  1663.     ritem[1] = goal->index;
  1664.     ritem[2] = 0;
  1665.     ritem[3] = -2;
  1666.     rlhs[0] = 0;
  1667.     rlhs[1] = 0;
  1668.     rlhs[2] = start_symbol;
  1669.     rrhs[0] = 0;
  1670.     rrhs[1] = 0;
  1671.     rrhs[2] = 1;
  1672.  
  1673.     j = 4;
  1674.     for (i = 3; i < nrules; ++i)
  1675.     {
  1676.     rlhs[i] = plhs[i]->index;
  1677.     rrhs[i] = j;
  1678.     assoc = TOKEN;
  1679.     prec = 0;
  1680.     while (pitem[j])
  1681.     {
  1682.         ritem[j] = pitem[j]->index;
  1683.         if (pitem[j]->class == TERM)
  1684.         {
  1685.         prec = pitem[j]->prec;
  1686.         assoc = pitem[j]->assoc;
  1687.         }
  1688.         ++j;
  1689.     }
  1690.     ritem[j] = -i;
  1691.     ++j;
  1692.     if (rprec[i] == UNDEFINED)
  1693.     {
  1694.         rprec[i] = prec;
  1695.         rassoc[i] = assoc;
  1696.     }
  1697.     }
  1698.     rrhs[i] = j;
  1699.  
  1700.     FREE(plhs);
  1701.     FREE(pitem);
  1702. }
  1703.  
  1704.  
  1705. static void print_grammar(void)
  1706. {
  1707.     register int i, j, k;
  1708.     int spacing;
  1709.     register FILE *f = verbose_file;
  1710.  
  1711.     if (!vflag) return;
  1712.  
  1713.     k = 1;
  1714.     for (i = 2; i < nrules; ++i)
  1715.     {
  1716.     if (rlhs[i] != rlhs[i-1])
  1717.     {
  1718.         if (i != 2) fprintf(f, "\n");
  1719.         fprintf(f, "%4d  %s :", i - 2, symbol_name[rlhs[i]]);
  1720.         spacing = strlen(symbol_name[rlhs[i]]) + 1;
  1721.     }
  1722.     else
  1723.     {
  1724.         fprintf(f, "%4d  ", i - 2);
  1725.         j = spacing;
  1726.         while (--j >= 0) putc(' ', f);
  1727.         putc('|', f);
  1728.     }
  1729.  
  1730.     while (ritem[k] >= 0)
  1731.     {
  1732.         fprintf(f, " %s", symbol_name[ritem[k]]);
  1733.         ++k;
  1734.     }
  1735.     ++k;
  1736.     putc('\n', f);
  1737.     }
  1738. }
  1739.  
  1740.  
  1741. void reader(void)
  1742. {
  1743.     write_section(banner);
  1744.     create_symbol_table();
  1745.     read_declarations();
  1746.     read_grammar();
  1747.     free_symbol_table();
  1748.     free_tags();
  1749.     pack_names();
  1750.     check_symbols();
  1751.     pack_symbols();
  1752.     pack_grammar();
  1753.     free_symbols();
  1754.     print_grammar();
  1755. }
  1756.